home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- Smaller Installer © 1996 Bill Goodman, All Rights Reserved
- *******************************************************************************
-
- Personalize Hook Example
-
- This installer hook procedure prompts the user to enter a name and organization
- string which is used to personalize the installed application. These strings
- are stored in an STR# resource (ID:1000) in the installed application. The user
- name is string #1 and the organization name is string #2. The strings are also
- saved in an "info" file on the installer startup disk so that subsequent
- installations will use the same personalization info.
-
- To build this hook procedure, compile this code and create a code resource
- (Type:SICR, ID:501, non-preloaded, nonpurgeable, unlocked, unprotected,
- non-sysheap). Add this resource to the "PersonalizeHook.rsrc" file. Copy all
- the resources in "PersonalizeHook.rsrc" to your installer's resource file.
-
- Set string #1 in the STR#:500 resource to specify the name of the application
- to be personalized.
-
- Copy the "Volume Info" file to the distribution disk containing the installer.
- This file must contain 512 bytes of data (preferably random in appearance).
- The first byte must be 0xFF. This file may be invisible if desired.
-
- Add an STR#:1000 resource to your application. The hook will modify the values
- in this resource after the application is installed. Add whatever code is
- appropriate to display these personalization strings in your application.
-
- ******************************************************************************/
-
- // This file is compatible with version 2.1 of the universal headers
- #include <Dialogs.h>
- #include <Files.h>
- #include <GestaltEqu.h>
- #include <LowMem.h>
- #include <SegLoad.h>
- #include <TextUtils.h>
-
- #ifdef __MWERKS__
- #include <A4Stuff.h>
- #endif
-
- #ifdef THINK_C
- #include <SetUpA4.h>
- #endif
-
- #include "SIHookProc.h"
-
-
- /******************************************************************************
- Function Prototypes
- ******************************************************************************/
- void AfterItemFunction(void);
- void FirstFunction(void);
-
-
- /******************************************************************************
- Constant Definitions
- ******************************************************************************/
- // Dialog Definitions
- #define nameDlg 500 // Name and organization entry dialog
- #define ok_nameDlg 1 // OK button
- #define name_nameDlg 3 // Name edit text item
- #define org_nameDlg 4 // Organization edit text item
-
- // Alert Definitions
- #define damagedAlrt 501 // "The installer disk is damaged. Please be sure you are using the original installer disk."
- #define nameErrAlrt 502 // "Please enter your name AND your organization's name."
- #define lockedAlrt 503 // "The installer disk is locked. Please unlock it and try again."
- #define installAlrt 504 // "An error occurred during installation. Please remove all files and try again."
-
- // Indexed String Definitions
- #define filenameID 500 // Filename string
- #define personalizeID 1000 // Personalization resource
-
-
- /******************************************************************************
- Variable Definitions
- ******************************************************************************/
- SIHookParmBlk *gParms; // Global pointer to parameter block
- Str31 infoFilename = "\pVolume Info"; // Name of info file
- Str255 gAppFilename; // Application filename
- Str255 gUserName; // User name string
- Str255 gUserOrg; // User organization string
-
-
- /*****************************************************************************/
- pascal void main(
- SIHookParmBlk *parmBlk // Pointer to parameter block
- )
- /******************************************************************************
- This is the main entry point for the installer hook procedure.
- ******************************************************************************/
- {
- #ifdef __MWERKS__
- long holdA4;
- #endif
-
- // Set up access to global variables
- #ifdef THINK_C
- RememberA0();
- SetUpA4();
- #endif
-
- #ifdef __MWERKS__
- holdA4 = SetCurrentA4();
- #endif
-
- gParms = parmBlk;
-
- switch (gParms->function)
- {
- case siHookFirst:
- FirstFunction();
- break;
-
- case siHookAfterItem:
- AfterItemFunction();
- break;
- }
-
- // Restore original A4 value
- #ifdef THINK_C
- RestoreA4();
- #endif
-
- #ifdef __MWERKS__
- SetA4(holdA4);
- #endif
- }
-
-
- /*****************************************************************************/
- void FirstFunction(void)
- /******************************************************************************
- Input parameters:
- "targetVRefNum" Volume reference number of target volume
- "groupAPFlags" Groups currently selected
- "groupQUSel"
- "groupVZSel"
- "group32Flags"
- "group64Flags"
- "group96Flags"
- "groupEnvironFlags"
-
- Returns:
- "groupAPFlags" Updated installation groups
- "groupQUSel"
- "groupVZSel"
- "group32Flags"
- "group64Flags"
- "group96Flags"
- "result" Hook result code (siHookNoErr, siHookQuit)
-
- This function is called once when the installer is launched.
- ******************************************************************************/
- {
- OSErr error;
- short infoPathNum = 0;
- long rwCnt;
- short index;
- DialogPtr dlgPtr;
- short item;
- short tmpType;
- Handle tmpHdl;
- Rect tmpRect;
-
- // Copy application name from resource into global string to speed up compares
- GetIndString(gAppFilename, filenameID, 1);
- if (gAppFilename[0] == 0)
- goto FatalError;
-
- // Open the info file
- error = HOpen(-LMGetSFSaveDisk(), fsRtDirID, infoFilename, fsCurPerm, &infoPathNum);
- if (error != noErr)
- goto InfoError;
-
- // Read the user name string
- rwCnt = 256;
- error = FSRead(infoPathNum, &rwCnt, gUserName);
- if (error != noErr)
- goto InfoError;
-
- // Read the user organization string
- rwCnt = 256;
- error = FSRead(infoPathNum, &rwCnt, gUserOrg);
- if (error != noErr)
- goto InfoError;
-
- if (gUserName[0] == 0xFF)
- { // Personalization strings have not been specified - prompt user to enter
- dlgPtr = GetNewDialog(nameDlg, NULL, (WindowPtr) -1L);
- if (dlgPtr == NULL)
- goto FatalError;
- for (;;)
- {
- ModalDialog(NULL, &item);
- if (item != ok_nameDlg)
- goto Terminate; // User cancelled dialog
-
- // Read strings from dialog
- GetDialogItem(dlgPtr, name_nameDlg, &tmpType, &tmpHdl, &tmpRect);
- GetDialogItemText(tmpHdl, gUserName);
- GetDialogItem(dlgPtr, org_nameDlg, &tmpType, &tmpHdl, &tmpRect);
- GetDialogItemText(tmpHdl, gUserOrg);
-
- // Validate strings
- if ((gUserName[0] != 0) && (gUserOrg[0] != 0))
- break;
-
- CautionAlert(nameErrAlrt, NULL); // "Entries are invalid"
- }
- DisposeDialog(dlgPtr);
-
- // Complement the characters in the name and organization strings to disguise them
- for (index = 256; --index >= 0;)
- gUserName[index] = ~gUserName[index];
-
- for (index = 256; --index >= 0;)
- gUserOrg[index] = ~gUserOrg[index];
-
- // Save the strings in the info file
- error = SetFPos(infoPathNum, fsFromStart, 0);
- if (error != noErr)
- goto InfoError;
-
- rwCnt = 256;
- error = FSWrite(infoPathNum, &rwCnt, gUserName);
- if (error != noErr)
- goto InfoError;
-
- rwCnt = 256;
- error = FSWrite(infoPathNum, &rwCnt, gUserOrg);
- if (error != noErr)
- goto InfoError;
- }
-
- // Complement the characters in the name and organization strings to
- // return the strings to normal format
- for (index = 256; --index >= 0;)
- gUserName[index] = ~gUserName[index];
-
- for (index = 256; --index >= 0;)
- gUserOrg[index] = ~gUserOrg[index];
-
- error = FSClose(infoPathNum);
- infoPathNum = 0;
- if (error != noErr)
- goto InfoError;
- return; // Good completion
-
- ///// Error exits /////
-
- // Error occured while accessing the info file
- InfoError:
- if ((error == vLckdErr) || (error == wPrErr))
- StopAlert(lockedAlrt, NULL); // "Volume is locked"
- else
- StopAlert(damagedAlrt, NULL); // "Disk is damaged"
- goto Terminate;
-
- // Fatal error occurred
- FatalError:
- SysBeep(1);
-
- // Cleanup and terminate
- Terminate:
- if (infoPathNum)
- FSClose(infoPathNum);
- gParms->result = siHookQuit; // Force installer to quit
- }
-
-
- /*****************************************************************************/
- void AfterItemFunction(void)
- /******************************************************************************
- Input parameters:
- "targetVRefNum" Volume reference number of target volume
- "groupAPFlags" Groups currently selected
- "groupQUSel"
- "groupVZSel"
- "group32Flags"
- "group64Flags"
- "group96Flags"
- "groupEnvironFlags"
- "filesRemaining" Number of files remaining to install or remove
- "bytesRemaining" Number of bytes of data remaining to install or remove
- "doingRemove" Non-zero if doing remove operation
- "anyItemsSkipped" Non-zero if any item has been skipped during operation
- "itemWasSkipped" Non-zero if this item was skipped
- "desVRefNum" Volume reference number of destination volume
- "desDirID" Directory ID of destination directory
- "itemName" Name of item that was installed or removed
- "itemIsFolder" Non-zero if item is a folder
- "fileType" File type (files only)
- "fileCreator" File creator (files only)
- "createDate" Creation date (files only)
- "lastModDate" Last modification date (files only)
- "rsrcForkLen" Length of resource fork (files only)
- "dataForkLen" Length of data fork (files only)
- "itemInfo" Reference passed from BeforeItem call
-
- Returns:
- "result" Hook result code (siHookNoErr, siHookQuit, siHookAbort)
-
- This function is called after each item is installed or removed.
- ******************************************************************************/
- {
- short applResFileNum = -1;
- Handle resHdl;
- long resSize;
- Byte buf[514];
-
- if (gParms->doingRemove)
- return; // No action required during remove operations
-
- if (gParms->itemWasSkipped)
- return; // No action required if item was skipped
-
- // Check to see if this item is the application file to customize
- if (!EqualString(gParms->itemName, gAppFilename, true, true))
- return; // Names do not match - no action required
-
- // Build the personalization resource
- buf[0] = 0;
- buf[1] = 2;
- BlockMove(gUserName, &buf[2], (short) gUserName[0] + 1);
- BlockMove(gUserOrg, &buf[(short) gUserName[0] + 3], (short) gUserOrg[0] + 1);
-
- // Open the installed application file
- SetResLoad(false); // Prevent loading of resources with preload attribute
- applResFileNum = HOpenResFile(gParms->desVRefNum, gParms->desDirID, gParms->itemName, fsRdWrPerm);
- SetResLoad(true);
- if (applResFileNum == -1)
- goto Fail;
-
- // Update the personalization resource in the installed application file
- resHdl = Get1Resource('STR#', personalizeID);
- if (resHdl == 0)
- goto Fail;
- resSize = (long) gUserName[0] + (long) gUserOrg[0] + 4;
- ReallocateHandle(resHdl, resSize);
- if (MemError() != noErr)
- goto Fail;
- BlockMove(buf, *resHdl, resSize);
- ChangedResource(resHdl);
- if (ResError() != noErr)
- goto Fail;
- WriteResource(resHdl);
- if (ResError() != noErr)
- goto Fail;
- CloseResFile(applResFileNum);
- if (ResError() != noErr)
- goto Fail;
- return; // Note that it is not necessary to set the result if no error
-
- // Error occurred during update
- Fail:
- if (applResFileNum != -1)
- CloseResFile(applResFileNum);
- StopAlert(installAlrt, NULL);
- gParms->result = siHookAbort;
- }
-